﻿using AnyCAD.AvaloniaUI;
using AnyCAD.Foundation;
using Avalonia.Controls.Shapes;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace AnyCadDemo.AvaloniaApp.ViewModels
{
    public partial class MainWindowViewModel : ViewModelBase
    {

        RenderControl renderControl { get; set; }

        public MainWindowViewModel(RenderControl _renderControl)
        {

            this.renderControl = _renderControl;

            ViewModelInitialization();

        }

        void ViewModelInitialization()
        {
            var shape = ShapeBuilder.MakeSphere(new GPnt(0, 0, 0), 10);


            var node = BrepSceneNode.Create(shape, null, null);
            var scene = renderControl.ViewContext.GetScene();
            scene.AddNode(node);

            renderControl.ViewContext.RequestUpdate(EnumUpdateFlags.Scene);

        }


        [RelayCommand]
        void ClickButtonCmd()
        {


            TopoShape shape = null;
            for (uint ii = 0; ii < 10; ++ii)
            {
                shape = ShapeBuilder.MakePyramid(new GAx2(new GPnt(ii * 11, 0, 0), GP.DZ()), ii + 3, 5, 5 + ii);

            }
            //   
            var node = BrepSceneNode.Create(shape, null, null);
            var scene = renderControl.ViewContext.GetScene();
            scene.Clear();
            scene.AddNode(node);

            renderControl.ViewContext.RequestUpdate(EnumUpdateFlags.Scene);

        }
        [RelayCommand]
        void SweptGenerateCmd()
        {
            var scene = renderControl.ViewContext.GetScene();

            var material = MeshStandardMaterial.Create("metal-double");
            material.SetColor(new Vector3(1.0f, 0.8f, 0.0f));
            material.SetMetalness(0.8f);
            material.SetRoughness(0.5f);
            material.SetFaceSide(EnumFaceSide.DoubleSide);


            var startPt = new GVec(0, 100, 0);
            var points = new GPntList();
            points.Add(new GPnt(startPt.XYZ()));
            points.Add(new GPnt(startPt.Added(new GVec(0, 0, 150)).XYZ()));
            points.Add(new GPnt(startPt.Added(new GVec(0, 100, 150)).XYZ()));
            points.Add(new GPnt(startPt.Added(new GVec(-100, 100, 150)).XYZ()));
            points.Add(new GPnt(startPt.Added(new GVec(-100, 300, 150)).XYZ()));
            points.Add(new GPnt(startPt.Added(new GVec(100, 300, 150)).XYZ()));
            TopoShape path = SketchBuilder.MakePolygon(points, false);

            var sectionList = new TopoShapeList();

            GAx2 coord1 = new GAx2(new GPnt(startPt.Added(new GVec(-25, -25, 0)).XYZ()), GP.DY());
            TopoShape section1 = SketchBuilder.MakeRectangle(coord1, 50, 50, 10, false);

            //scene.AddNode(section1);
            //scene.AddNode(path);
            //var nodeSec1 = BrepSceneNode.Create(section1, ColorTable.Red, null);
            //var nodePath = BrepSceneNode.Create(section1, ColorTable.Green, null);
            //renderControl.ShowShape(section1, ColorTable.Red);
            //renderControl.ShowShape(path, ColorTable.Green);

            TopoShape pipe = FeatureTool.SweepByFrenet(section1, path, EnumSweepTransitionMode.RoundCorner,
                false);
            BufferShape bs = new BufferShape(pipe, material, null, 0.1f);
            bs.Build();
            var node = new BrepSceneNode(bs);
            scene.AddNode(node);

            renderControl.ViewContext.RequestUpdate(EnumUpdateFlags.Scene);
        }



        [RelayCommand]
        void SweptPipeGenerateCmd()
        {
            //获得当前场景
            var scene = renderControl.ViewContext.GetScene();

            //当前路径点
            GPntList points = new GPntList
                {
                   // GP.Origin(),
                    new GPnt(10, 10, 0),
                    new GPnt(20, 20, 0),
                    new GPnt(30, 130, 0),
                       new GPnt(80, 130, 0),
                    //new GPnt(70, 60, 80),
            };
          
            //两个空间点转 vec 或 dir 的方法
            //GDir normal = new GDir( new GVec(points[0], points[1])  );

            //放样路径
            // var path = SketchBuilder.MakePolygon(points,false);
            var path = SketchBuilder.MakeBSpline(points, false);
            var curve = new ParametricCurve(path);
            var rt = curve.D1(curve.FirstParameter());
            //放样草图位置所在位置
            GPnt position = rt.GetPoint();  //     GVec GVec.Transformed(GTrsf   theT)
            //放样草图方向的法线
            GDir normal = new GDir(rt.GetVectors()[0].Normalized());
            GDir rightDir = normal.Crossed(GP.DZ());

            /**/
            //position = new GPnt(position.x+ rightDir.x, position.y + rightDir.y, position.z);   ;

            //绘制放样草图  最后的方向控制为 右向量 及 法线    
            var sketch = SketchBuilder.MakeEllipse(position, 5, 3, rightDir, normal);

            //绘制路径线实体
            var nodePath = BrepSceneNode.Create(path, null, null);
            scene.AddNode(nodePath);

            //开始放样   这里注意针对B样条会有反转问题  需要调整
            var feature = FeatureTool.SweepByFrenet(sketch, path, EnumSweepTransitionMode.Transformed,
                false, false, true);
            var nodeSweep = BrepSceneNode.Create(feature, faceMaterial: null, null);
            scene.AddNode(nodeSweep);


            foreach (var point in points)
            {
                var shape = ShapeBuilder.MakeSphere(point, 2);
                var node = BrepSceneNode.Create(shape, null, null);
                scene.AddNode(node);
            }

            //更新当前场景
            renderControl.ViewContext.RequestUpdate(EnumUpdateFlags.Scene);

        }

    }
}
